package model

import (
	"encoding/json"
	"fmt"

	"github.com/gomodule/redigo/redis"
)

//我们再服务器启动后就初始化一个userDao的实例
//把它做成全局变量，服务一启动就实例化，方便后面调用

var (
	MyUserDao *UserDao
)

//定义一个 UserDao 结构体体
//完成对 User 结构体的各种操作.
type UserDao struct {
	pool *redis.Pool
}

//使用工厂模式，创建一个 UserDao 实例
func NewUserDao(pool *redis.Pool) (userDao *UserDao) {
	fmt.Println("")
	userDao = &UserDao{
		pool: pool,
	}
	return userDao
}

//根据用户 id 返回 一个 User 实例+err
func (this *UserDao) getUserById(conn redis.Conn, id int) (user *User, err error) {

	//通过给定的id去redis查询数据
	fmt.Println("需要查询用户的id:", id)
	res, err := redis.String(conn.Do("hget", "users", id))
	if err != nil {
		if err == redis.ErrNil {
			fmt.Println("通过给定的id去redis查询数据失败,err=", err)
			err = ErrOR_USER_NOTEXISTS
		}

		return nil, err
	}

	//将查询到的res反序列化给user结构体，然后返回
	err = json.Unmarshal([]byte(res), &user)
	if err != nil {
		fmt.Println("将查询到的res反序列化给user失败,err=", err)
		return
	}

	fmt.Println("查询到的user=:", res)
	return
}

//服务端校验登录
//1. Login 完成对用户的验证
//2. 如果用户的 id 和 pwd 都正确，则返回一个 user 实例
//3. 如果用户的 id 或 pwd 有错误，则返回对应的错误信息
func (this *UserDao) Login(userId int, userPwd string) (user *User, err error) {

	//先从 UserDao 的连接池中取出一根连接
	conn := this.pool.Get()
	defer conn.Close()

	user, err = this.getUserById(conn, userId)
	if err != nil {

		fmt.Println("根据id查询不到输入的用户")
		return
	}
	//这时证明这个用户是获取到
	if user.UserPwd != userPwd {
		err = ErrOR_USER_PWD
		return
	}

	return
}

func (this *UserDao) Register(user *User) (err error) {

	//先从 UserDao 的连接池中取出一根连接
	conn := this.pool.Get()
	defer conn.Close()

	fmt.Println("userProcess传来的user对象:", user.UserId)

	var re *User
	re, err = this.getUserById(conn, user.UserId)

	fmt.Println("注册时候先查询是否redis已存在相同的id,res:", re)
	if err == nil {

		fmt.Println("redis中存在相同的用户")
		err = ErrOR_USER_EXISTS
		return
	}
	//走到这一步说明redis中没有相关的用户数据，可以继续注册
	// var user User = User{
	// 	UserId:   userId,
	// 	UserPwd:  userPwd,
	// 	UserName: userName,
	// }
	data, err := json.Marshal(user)
	if err != nil {
		fmt.Println("注册信息序列化失败...,err=", err)
		return
	}

	//入库
	_, err = conn.Do("hset", "users", user.UserId, string(data))
	if err != nil {
		fmt.Println("注册用户失败...")
		return
	}
	return
}
